#include <stdarg.h>
#include <stdint.h>
#include "formatted_io.h"

void formatted_io::print(char c)
{ send(c); }

void formatted_io::print(const char* s)
{
  while(*s) {
    send(*s);
    ++s;
  }
}

void formatted_io::print(unsigned i, unsigned base)
{
  unsigned q = i / base;
  unsigned r = i % base;

  if(q != 0)
    print(q, base);

  if(r < 10)
    send(r + '0');
  else
    send(r-10 + 'A');
}

void formatted_io::print(float f, unsigned places)
{
  int i = (int)f;

  // print integer part
  print(i);

  print('.');

  // get fraction part
  f -= i;
  if(f < 0)
    f = -f;

  while(f > 0.0 && places) {
    f *= 10.0;
    unsigned ipart = f;
    f -= ipart;
    print(ipart);
    places--;
  }
}

void formatted_io::print(int i, unsigned base)
{
  unsigned uns;
  if(i < 0) {
    send('-');
    uns = -i;
  } else {
    uns = i;
  }
  print(uns, base);
}

void formatted_io::printf(const char * str, ...)
{
  va_list arp;
  int d, r, w, s, l;


  va_start(arp, str);

  while ((d = *str++) != 0) {
    if (d != '%') {
      print((char)d);
      continue;
    }
    d = *str++; w = r = s = l = 0;
    if (d == '0') {
      d = *str++; s = 1;
    }
    while ((d >= '0')&&(d <= '9')) {
      w += w * 10 + (d - '0');
      d = *str++;
    }
    if (s) w = -w;
    if (d == 'l') {
      l = 1;
      d = *str++;
    }
    if (!d) break;
    if (d == 's') {
      print(va_arg(arp, char*));
      continue;
    }
    if (d == 'c') {
      print((char)va_arg(arp, int));
      continue;
    }
    if (d == 'f') {
      print((float)(va_arg(arp, double)));
      continue;
    }
    if (d == 'u') r = 10;
    if (d == 'd') r = -10;
    if (d == 'X' || d == 'x') r = 16; 
    if (d == 'b') r = 2;
    if (!r) break;
    /*if (l) {
      xitoa(u,(long)va_arg(arp, long), r, w);
    } else {
      if (r > 0)
        xitoa(u,(unsigned long)va_arg(arp, int), r, w);
      else
        xitoa(u,(long)va_arg(arp, int), r, w);
    }*/
  }

  va_end(arp);
}

char formatted_io::read_char()
{
  return receive();
}

bool formatted_io::char_avail()
{
  return char_avail_fun();
}

int formatted_io::read_int()
{
  char c;
  int res = 0;
  bool neg = false;
  c = receive();
  if(c == '-') {
    neg = true;
    c = receive();
  }
  while(c >= '0' && c <= '9') {
    res *= 10;
    res += c - '0';
    c = receive();
  }
  if(neg)
    return -res;
  else
    return res;
}
